package com.lin.util;


import lombok.extern.slf4j.Slf4j;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.hssf.util.HSSFColor;
import org.jetbrains.annotations.NotNull;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

/**
 * excel导出工具
 *
 * @author 九分石人，2019-12-31
 */
@Slf4j
public class ExcelExportUtil {


    /**
     * 导出Excel主方法，调用此方法即可(该方法未测试)
     *
     * @param <T>      类型泛型
     * @param fileName 文件名
     * @param list     数据源
     * @param title    标题数组
     * @param response 返回输出流
     * @author com.lin, 2019-12-20
     */
    public static <T> void exportExcel(String fileName, @NotNull List<T> list, String[] title, HttpServletResponse response) {
        // 制作导出文件
        HSSFWorkbook excel;
        int maxNum = 5000;
        try {
            if (list.size() > maxNum) {
                fileName = "数据量过大";
                List<String> listError = new ArrayList<>();
                listError.add("数据量超过5000，无法导出");
                String[] titleError = new String[]{"数据量超过5000，无法导出"};
                excel = ExcelExportUtil.getExcel(list, titleError);
            } else {
                // 制作导出文件
                excel = ExcelExportUtil.getExcel(list, title);
            }

            fileName = new String((fileName + ".xls").getBytes(), StandardCharsets.ISO_8859_1);

            response.setContentType("application/octet-stream;charset=ISO-8859-1");
            response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
            response.addHeader("Pargam", "no-cache");
            response.addHeader("Cache-Control", "no-cache");

            // 写入输出流
            OutputStream os = response.getOutputStream();
            excel.write(os);
            os.flush();
            os.close();
        } catch (IOException | IllegalAccessException e) {
            log.error(e.getMessage());
        }
    }


    /**
     * 制作HSSFWorkbook格式的Excel文件
     *
     * @param <T>   类型泛型
     * @param list  数据源，要导出的数据
     * @param title 标题列表
     * @return excel格式的文件
     * @throws IllegalAccessException 反射报错
     * @author com.lin, 2019-12-20
     */
    @NotNull
    public static <T> HSSFWorkbook getExcel(List<T> list, @NotNull String[] title) throws IllegalAccessException {

        // 创建一个excel文件
        HSSFWorkbook wb = new HSSFWorkbook();
        HSSFSheet sheet = wb.createSheet("sheet1");
        sheet.setDefaultColumnWidth(20);

        // 设置标题样式
        HSSFFont titlefontStyle = wb.createFont();
        titlefontStyle.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
        titlefontStyle.setFontHeightInPoints((short) 15);

        HSSFCellStyle titleCellStyle = wb.createCellStyle();
        titleCellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
        titleCellStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
        titleCellStyle.setFillBackgroundColor(HSSFColor.YELLOW.index);
        titleCellStyle.setFont(titlefontStyle);

        HSSFRow titlterow = sheet.createRow(0);
        titlterow.setHeightInPoints(20);
        HSSFCell cell;

        for (int i = 0; i < title.length; i++) {
            cell = titlterow.createCell(i);
            cell.setCellValue(title[i]);
            cell.setCellStyle(titleCellStyle);
        }

        // 设置内容样式
        HSSFRow row;

        HSSFFont fontStyle = wb.createFont();
        fontStyle.setFontHeightInPoints((short) 12);

        HSSFCellStyle cellStyle = wb.createCellStyle();
        cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
        cellStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
        cellStyle.setFont(fontStyle);

        // 设置excel数据
        for (int i = 0; i < list.size(); i++) {
            T t = list.get(i);
            row = sheet.createRow(i + 1);
            row.setHeightInPoints(15);
            // 通过反射获取对象的值并设置进excel
            Class c = t.getClass();
            Field[] fields = c.getDeclaredFields();
            for (int j = 0; j < fields.length; j++) {
                Field f = fields[j];
                f.setAccessible(true);
                if (f.get(t) != null) {
                    row.createCell(j).setCellValue(f.get(t).toString());
                } else {
                    row.createCell(j);
                }
            }
        }
        return wb;
    }

}
